package com.blakequ.androidblemanager.utils;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Looper;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.Gravity;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class CrashHandler implements UncaughtExceptionHandler {
    public final static String versionTag = "";
    private final String TAG = "CrashHandler";
    private UncaughtExceptionHandler mDefaultHandler;
    private static CrashHandler INSTANCE;
    private Context mContext;
    private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
    private Map<String, String> infos = new HashMap<String, String>();
    private String crashDir = "/crash/";
//    private ExceptionLogModel exceptionEntity = new ExceptionLogModel();

    private CrashHandler() {
    }

    public static CrashHandler getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new CrashHandler();
        }
        return INSTANCE;
    }

    public void init(Context ctx, String dir) {
        mContext = ctx;
        crashDir = dir;
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        if (!handleException(ex) && mDefaultHandler != null) {
            mDefaultHandler.uncaughtException(thread, ex);
        } else {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                Log.e(TAG, "error : ", e);
            }
            try {
//                RxActivityTool.finishAllActivity();
                android.os.Process.killProcess(android.os.Process.myPid());
                System.exit(1);
                System.gc();
            } catch (Exception e) {

            }

//            Intent intent = new Intent(mContext, LuancherActivity.class);
//            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
//                    Intent.FLAG_ACTIVITY_NEW_TASK);
//            mContext.startActivity(intent);

//            Intent intent = new Intent(mContext.getApplicationContext(), LuancherActivity.class);
//            PendingIntent restartIntent = PendingIntent.getActivity(
//                    mContext.getApplicationContext(), 0, intent,
//                    Intent.FLAG_ACTIVITY_NEW_TASK);
//            //退出程序
//            AlarmManager mgr = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
//            mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000,
//                    restartIntent); // 1秒钟后重启应用
        }
    }

    private boolean handleException(final Throwable ex) {
        Log.e(TAG, "handleException : ", ex);
        if (ex == null) {
            return true;
        }

        new Thread() {
            @Override
            public void run() {
                try {
                    Looper.prepare();
                    Toast toast = Toast.makeText(mContext, "程序开个小差，正在退出", Toast.LENGTH_LONG);
                    toast.setGravity(Gravity.CENTER, 0, 0);
                    toast.show();

                    collectDeviceInfo(mContext);

                    saveCrashInfo2File(ex);

                    Looper.loop();
                } catch (Exception e) {
                }

            }
        }.start();

        return true;
    }


    private String saveCrashInfo2File(Throwable ex) {

        StringBuffer sb = new StringBuffer();
        for (Map.Entry<String, String> entry : infos.entrySet()) {
            try {
                String key = entry.getKey();
                String value = entry.getValue();
                sb.append(key + "=" + value + "\n");
            } catch (Exception e) {

            }
        }

        Writer writer = new StringWriter();
        PrintWriter printWriter = new PrintWriter(writer);
        ex.printStackTrace(printWriter);
        Throwable cause = ex.getCause();
        while (cause != null) {
            cause.printStackTrace(printWriter);
            cause = cause.getCause();
        }
        printWriter.close();
        String result = writer.toString();
        sb.append(result);
        Log.e(TAG, "异常退出错误：" + sb.toString());
        try {
            long timestamp = System.currentTimeMillis();
            DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String time = formatter.format(new Date());
            // start 添加错误日志到数据库
//            exceptionEntity.setReportTime((int) (System.currentTimeMillis()) + "");
//            exceptionEntity.setReportText(result);
//            // 网络连接状态(0:未连接, 1:已连接, 2:未检测到)
//            exceptionEntity.setNetConnected(AppUtils.isNetworkAvailable(mContext) ? "1" : "0");
//            exceptionEntity.setNetType(getNetworkType(mContext));
////            CrashUtils.getDao().addLogToSdCard("程序崩溃：\n"+exceptionEntity.toString());
////            String UserIdOrPhoneNumber = "userId="+ UserDataManager.getDao().getUserId()+
////                    "phoneNumber="+UserDataManager.getDao().getUserPhoneNumber();
//            Log.e("程序崩溃", exceptionEntity.toString());
//            CrashUtils.getInstance().netSubmitLog(AiyigeExceptionModel.type_app_crash, "程序崩溃：\n" + result, AiyigeExceptionModel.rating_4);
//            ExceptionUtils.uploadAppCrash("App闪退了：\n" + result);
            // end 添加错误日志到数据库
            String fileName = "crash-" + time + "-" + timestamp + ".log";
            File dir = AppUtils.createOrExistsDir("crash");
            FileOutputStream fos = new FileOutputStream(new File(dir, fileName));
            fos.write(result.getBytes());
            fos.close();

            return fileName;
        } catch (Exception e) {
            Log.e(TAG, "an error occured while writing file...", e);
        }
        return null;
    }


    public void collectDeviceInfo(Context ctx) {
        try {
            PackageManager pm = ctx.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES);
            if (pi != null) {
                String versionName = pi.versionName == null ? "null" : pi.versionName;
                String versionCode = pi.versionCode + "";
                infos.put("versionName", versionName);
                infos.put("versionCode", versionCode);
            }
        } catch (NameNotFoundException e) {
            Log.e(TAG, "an error occured when collect package info", e);
        }
        Field[] fields = Build.class.getDeclaredFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                infos.put(field.getName(), field.get(null).toString());
                Log.d(TAG, field.getName() + " : " + field.get(null));
            } catch (Exception e) {
                Log.e(TAG, "an error occured when collect crash info", e);
            }
        }
    }


    public static String getNetworkType(Context context) {
        String strNetworkType = "";
        ConnectivityManager cm = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = cm.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isConnected()) {
            if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
                strNetworkType = "WIFI";
            } else if (networkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
                String _strSubTypeName = networkInfo.getSubtypeName();

                // TD-SCDMA networkType is 17
                int networkType = networkInfo.getSubtype();
                switch (networkType) {
                    case TelephonyManager.NETWORK_TYPE_GPRS:
                    case TelephonyManager.NETWORK_TYPE_EDGE:
                    case TelephonyManager.NETWORK_TYPE_CDMA:
                    case TelephonyManager.NETWORK_TYPE_1xRTT:
                    case TelephonyManager.NETWORK_TYPE_IDEN: // api<8 : replace by
                        // 11
                        strNetworkType = "2G";
                        break;
                    case TelephonyManager.NETWORK_TYPE_UMTS:
                    case TelephonyManager.NETWORK_TYPE_EVDO_0:
                    case TelephonyManager.NETWORK_TYPE_EVDO_A:
                    case TelephonyManager.NETWORK_TYPE_HSDPA:
                    case TelephonyManager.NETWORK_TYPE_HSUPA:
                    case TelephonyManager.NETWORK_TYPE_HSPA:
                    case TelephonyManager.NETWORK_TYPE_EVDO_B: // api<9 : replace by
                        // 14
                    case TelephonyManager.NETWORK_TYPE_EHRPD: // api<11 : replace by
                        // 12
                    case TelephonyManager.NETWORK_TYPE_HSPAP: // api<13 : replace by
                        // 15
                        strNetworkType = "3G";
                        break;
                    case TelephonyManager.NETWORK_TYPE_LTE: // api<11 : replace by
                        // 13
                        strNetworkType = "4G";
                        break;
                    default:
                        // http://baike.baidu.com/item/TD-SCDMA 中国移动 联通 电信 三种3G制式
                        if (_strSubTypeName.equalsIgnoreCase("TD-SCDMA")
                                || _strSubTypeName.equalsIgnoreCase("WCDMA")
                                || _strSubTypeName.equalsIgnoreCase("CDMA2000")) {
                            strNetworkType = "3G";
                        } else {
                            strNetworkType = _strSubTypeName;
                        }

                        break;
                }
            }
        }
        return strNetworkType;
    }

//    public static void addLogToSdCard(String log) {
//        try {
//            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
//                File dir = new File(PLAYER_LOG_PATH);
//                if (!dir.exists()) {
//                    dir.mkdirs();
//                }
//                String time = TimeUtils.dateToYYYYMMDDHHSS(System.currentTimeMillis(),"yyyy-MM-dd HH:mm:ss.SSS");
//                log = time + "\n" + log + "\n\n";
//                FileWriter fw = null;
//                try {
//                    //如果文件存在，则追加内容；如果文件不存在，则创建文件
//                    File f = new File(PLAYER_LOG_PATH + PLAYER_LOG_PATH_FILE_NAME);
//                    fw = new FileWriter(f, true);
//                } catch (Exception e) {
//                    e.printStackTrace();
//                }
//                PrintWriter pw = new PrintWriter(fw);
//                pw.println(log);
//                pw.flush();
//                try {
//                    fw.flush();
//                    pw.close();
//                    fw.close();
//                } catch (Exception e) {
//                    e.printStackTrace();
//                }
//            }
//        } catch (Exception e) {
//            if (e != null) {
//                Log.e("",""+e.toString());
//            }
//        }
//    }

//    public static void addLogToSdCard(FragmentActivity activity, String log) {
//        try {
//            String className = getClassName(activity);
//            Log.d("PlayerDebug",TimeUtils.dateToYYYYMMDDHHSS(System.currentTimeMillis(),"yyyy-MM-dd HH:mm:ss.SSS") + " "+className + " "+log);
//            addLogToSdCard( className+ ":"+log);
//        } catch (Exception e) {
//            if (e != null) {
//                Log.e("",""+e.toString());
//            }
//        }
//    }

//
//    public static void _exportLog(FragmentActivity activity, String audioLocalUrl) {
//        try {
//            if (TextUtils.isEmpty(audioLocalUrl)) {
//                ToastX.show("音乐路径不能为空");
//                return;
//            }
//            if (!RxFileTool.fileExists(audioLocalUrl)) {
//                ToastX.show("音乐路径不能为空");
//                return;
//            }
//            Uri uri;
//            Intent shareIntent = new Intent(Intent.ACTION_SEND);
//            if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
//                uri = Uri.fromFile(new File(audioLocalUrl));
//            } else {
//                /**
//                 * Android 7.0文件分享适配
//                 */
//                uri = FileProvider.getUriForFile(activity, activity.getPackageName() + ".provider", new File(audioLocalUrl));
//            }
//            shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
//            shareIntent.setType("text/plain");//此处可发送多种文件
//            List<ResolveInfo> packages = activity.getPackageManager().queryIntentActivities(shareIntent, 0);
//            List<Intent> targetIntents = new ArrayList<Intent>();
//            for (ResolveInfo candidate : packages) {
//                String packageName = candidate.activityInfo.packageName;
//                Intent target = new Intent(Intent.ACTION_SEND);
//                target.setType("text/plain");
//                if (uri != null) {
//                    target.setType("text/plain");
//                    target.putExtra(Intent.EXTRA_STREAM, uri);
//                }
//                target.putExtra(Intent.EXTRA_TEXT, "导出到：");
//                target.setComponent(new ComponentName(packageName, candidate.activityInfo.name));
//                if (candidate.activityInfo.packageName.equals(activity.getPackageName())) {
//                    continue;
//                }
//                targetIntents.add(target);
//            }
//            Intent chooserIntent = Intent.createChooser(targetIntents.remove(0), "导出到：");
//            chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetIntents.toArray(new Parcelable[]{}));
//            activity.startActivity(chooserIntent);
//        } catch (Exception e) {
//            Log.e("", "" + e.toString());
//        }
//    }

}
